package com.sj.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sj.common.exception.CustomException;
import com.sj.common.lang.ApiResultMsg;
import com.sj.common.lang.ResultInfo;
import com.sj.entity.Blog;
import com.sj.entity.Tag;
import com.sj.service.TagService;
import com.sj.utils.MarkdownUtils;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 博客模块前端控制器
 * </p>
 *
 * @author 小七
 * @since 2021-07-30
 */
@Api(tags = "博客模块")
@RestController
@RequestMapping("/api/blog")
public class BlogController extends BaseController {


    @Autowired
    private TagService tagService;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;


    @DeleteMapping("/delete-tag-bind-blog/{tagId}/{blogId}")
    @ApiOperation(value = "解除博客和标签的绑定")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tagId", value = "标签id"),
            @ApiImplicitParam(name = "blogId", value = "博客id")
    })
    public ApiResultMsg<Tag> deleteTagBindBlog(@PathVariable("tagId") Integer tagId, @PathVariable("blogId") Integer blogId) {
        boolean result = blogService.tagIsBindBlog(tagId, blogId);
        if (result) {
            List<Tag> tagList = tagService.getTagListByBlogId(blogId);
            if (tagList.size() == 1) {
                return ApiResultMsg.error("至少保留一个标签，请先编辑");
            }
            result = blogService.deleteTagBindBlog(tagId, blogId);
            if (result) {
                return ApiResultMsg.success(ResultInfo.SUCCESS);
            }
        }
        return ApiResultMsg.error(ResultInfo.ERROR);
    }

    @GetMapping("/detail")
    @ApiOperation(value = "博客详情接口")
    public ApiResultMsg<Blog> blogDetail(@RequestParam("blogId") @ApiParam(name = "blogId", value = "博客id") Integer blogId,
                                         @RequestParam(value = "userId", required = false) @ApiParam(name = "userId", value = "用户id") Integer userId) {
        Blog blog = blogService.getBlogDetail(blogId, null, userId);
        if (blog != null) {
            List<Tag> tagList = tagService.getTagListByBlogId(blogId);
            blog.setTagList(tagList);
            blog.setHtmlContent(MarkdownUtils.markdownToHtmlExtensions(blog.getContent()));
            return ApiResultMsg.success(ResultInfo.SUCCESS, blog);
        }
        return ApiResultMsg.error(ResultInfo.NOT_FONT);
    }

    @DeleteMapping("/delete/{userId}/{id}")
    @ApiOperation(value = "删除博客接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id"),
            @ApiImplicitParam(name = "id", value = "博客id"),
    })
    public ApiResultMsg<Blog> delete(@PathVariable("userId") Integer userId, @PathVariable("id") Integer id) {
        boolean result = blogService.remove(new QueryWrapper<Blog>().eq("id", id).eq("user_id", userId));
        if (result) {
            return ApiResultMsg.success(ResultInfo.SUCCESS);
        }
        return ApiResultMsg.error(ResultInfo.ERROR);
    }

    @PostMapping("/update")
    @ApiOperation(value = "根据id更新博客接口", notes = "没有校验，只更新传值了的属性")
    public ApiResultMsg<Blog> updateById(@RequestBody Blog blog) {
        boolean result = blogService.update(blog, new QueryWrapper<Blog>().eq("id", blog.getId()).eq("user_id", blog.getUserId()));
        if (result) {
            return ApiResultMsg.success(ResultInfo.SUCCESS);
        }
        return ApiResultMsg.error(ResultInfo.ERROR);
    }


    @PutMapping("/save")
    @ApiOperation(value = "添加更新博客接口", notes = "通过是否有id执行添加或者更新，标签可添加多个，如果添加的标签不存在则先添加标签")
    public ApiResultMsg<Blog> save(@RequestBody @Validated Blog blog) {
        // 配置事务
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = platformTransactionManager.getTransaction(defaultTransactionDefinition);
        try {
            boolean result = blogService.saveOrUpdate(blog, new QueryWrapper<Blog>().eq("id", blog.getId()).eq("user_id", blog.getUserId()));
            // 添加博客成功
            if (result) {
                // 获取博客的需要添加的标签列表
                String[] ids = blog.getTagNames().split(",");
                // 存放需要与当前博客绑定的标签id
                ArrayList<Integer> wantBindBlogTagIds = new ArrayList<Integer>();
                Arrays.stream(ids).forEach(item -> {
                    Tag saveTag = null;
                    boolean saveFlag = true;
                    // 获取该用户是否有当前标签
                    saveTag = tagService.getOne(new QueryWrapper<Tag>().eq("tag_name", item).eq("user_id", blog.getUserId()));
                    // 如果没有 先添加标签
                    if (saveTag == null) {
                        saveTag = new Tag();
                        saveTag.setTagName(item);
                        saveTag.setUserId(blog.getUserId());
                        saveFlag = tagService.save(saveTag);
                    }
                    if (!saveFlag) {
                        throw new CustomException(item + "标签添加失败");
                    }
                    // 添加成功标签后 与该博客绑定
                    wantBindBlogTagIds.add(saveTag.getId());
                });
                boolean bindTagFlag = blogService.bindTags(wantBindBlogTagIds, blog.getId());
                if (!bindTagFlag) {
                    throw new CustomException("绑定标签失败");
                }
                // 执行成功 提交事务
                platformTransactionManager.commit(status);
                return ApiResultMsg.success(ResultInfo.SUCCESS);
            }
            return ApiResultMsg.error(ResultInfo.ERROR);
        } catch (CustomException e) {
            // 捕获异常 回滚事务 将异常抛出给全局异常处理器
            platformTransactionManager.rollback(status);
            throw e;
        }
    }

    @GetMapping("/list")
    @ApiOperation(value = "查询博客列表", notes = "分页，带有多条件查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页", required = false, defaultValue = "1"),
            @ApiImplicitParam(name = "size", value = "每页显示条数", required = false, defaultValue = "10"),
    })
    public ApiResultMsg<Blog> listBlog(Blog blog, @RequestParam(value = "current", defaultValue = "1", required = false) Integer current,
                                       @RequestParam(value = "size", defaultValue = "10", required = false) Integer size) {
        IPage<Blog> blogPageInfo = blogService.listBlogByPage(blog, current, size);
        return ApiResultMsg.success(ResultInfo.SUCCESS, blogPageInfo);
    }

}

